package main.java.com.lee.lock;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description 死锁检测
 */
public class DeadLockMonitor {
    public static void main(String[] args) {
//        Object lock1 = new Object();
//        Object lock2 = new Object();
        var lock1 = new ReentrantLock();
        var lock2 = new ReentrantLock();

        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                lock1.lock();
                try{
                    System.out.println(Thread.currentThread().getName() + "获取到了lock1");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try{
                        lock2.lockInterruptibly();
                        System.out.println(Thread.currentThread().getName() + "获取到了lock2");
                    } catch (InterruptedException e){
//                        e.printStackTrace();
                        System.out.println(Thread.currentThread().getName() + "被中断了" + interrupted());
                    }finally {
                        lock2.unlock();
                    }
                }finally {
                    lock1.unlock();
                }
//                synchronized (lock1) {
//                    System.out.println(Thread.currentThread().getName() + "获取到了lock1");
//                    try {
//                        Thread.sleep(1000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    synchronized (lock2) {
//                        System.out.println(Thread.currentThread().getName() + "获取到了lock2");
//                    }
//                }
            }
        };

        Thread t2 = new Thread("t2") {
            @Override
            public void run() {

                lock2.lock();
                try{
                    System.out.println(Thread.currentThread().getName() + "获取到了lock2");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    try{
                        lock1.lockInterruptibly();
                        System.out.println(Thread.currentThread().getName() + "获取到了lock1");
                    }catch (InterruptedException e){
//                        e.printStackTrace();
                        System.out.println(Thread.currentThread().getName() + "被中断了" + interrupted());
                    }
                    finally {
                        lock1.unlock();
                    }
                }finally {
                    lock2.unlock();
                }

//                synchronized (lock2) {
//                    System.out.println(Thread.currentThread().getName() + "获取到了lock2");
//                    try {
//                        Thread.sleep(1000);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    synchronized (lock1) {
//                        System.out.println(Thread.currentThread().getName() + "获取到了lock1");
//                    }
//                }
            }
        };

        t1.start();
        t2.start();

        LockSupport.parkNanos(5000000000L);


        var threadMXBean = ManagementFactory.getThreadMXBean();
        var deadlockedThreads = threadMXBean.findDeadlockedThreads();
        if (deadlockedThreads != null) {
            for (var deadlockedThread : deadlockedThreads) {
                var threadInfo = threadMXBean.getThreadInfo(deadlockedThread, Integer.MAX_VALUE);
                System.out.println(threadInfo);
                if(threadInfo.getThreadName().equals("t1")){
                    t1.interrupt();
                }else {
                    t2.interrupt();
                }
            }
        }
    }
}
